package solvers;

import java.util.Random;

/**
 * Created by IntelliJ IDEA.
 * User: dmitry
 * Date: 07.04.12
 * Time: 21:55
 * To change this template use File | Settings | File Templates.
 */
public final class SimpleMutator implements Mutator {
    private static final SimpleMutator INSTANCE = new SimpleMutator();
    
    private static final double MAX_MUTATIONS_PART = 0.25;

    public static SimpleMutator getInstance() {
        return INSTANCE;
    }

    @Override
    public int[] mutate(int[] x, int p) {
        if(x == null)
            throw new IllegalArgumentException("null");
        if(x.length == 0)
            throw new IllegalArgumentException("x.length == 0");
        if(p <0 )
            throw new IllegalArgumentException("p < 0");
        if(p > x.length)
            throw new IllegalArgumentException("p > x.length");
        final int result[] = new int[x.length];
        System.arraycopy(x,0,result,0,x.length);

        final int mutationsNumber = Math.min(p,(int)(x.length * MAX_MUTATIONS_PART / 2));
        
        final Random random = new Random(System.currentTimeMillis());
        //changing mutationNumber random values
        for(int i = 0 ; i < mutationsNumber ; ++i) {
            final int zeroIndex = getRandomIndexOfValue(random,result,0);
            final int oneIndex = getRandomIndexOfValue(random,result,1);
            if(zeroIndex < 0 || oneIndex < 0)//can not change solution without making it worse
                return result;
            result[zeroIndex] = 1;
            result[oneIndex] = 0;
        }
        
        //fixing of condidion |x| == p

        return result;
    }
    
    private static int getRandomIndexOfValue(Random random, int [] x, int value) {
        final int randomIndex = random.nextInt(x.length);
        for(int i = 0 ; i < x.length ; ++i) {
            final int j = (randomIndex +i)%x.length;
            if(x[j] == value)
                return j;
        }
        return -1;//no value in array;
    }
}
